#include "mySerial.h"

#include <stdbool.h>
#include <stdlib.h>

#include <TM4C123GH6PM.h>
#include "driverlib/sysctl.h"
#include "driverlib/gpio.h"
#include "driverlib/uart.h"
#include "driverlib/pin_map.h"
#include "driverlib/interrupt.h"
#include "inc/hw_ints.h"
#include "inc/hw_gpio.h"
#include "inc/hw_types.h"
#include "utils/uartstdio.h"

#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"

#include "myTimer/myTimer.h"
#include "MOTOR/motor.h"

uartBuf_t uart0Buf;
uartBuf_t uart2Buf;

QueueHandle_t uart0Queue = NULL;
QueueHandle_t uart2Queue = NULL;

/**
 * @brief    serial0_handle_Task 任务函数
 * @brief    负责处理串口0传输的数据
 */
void serial0_handle_Task(void *pvParameters)
{
  uartBuf_t uart0Buf;
  uint8_t *data = NULL;
  while (1){
    xQueueReceive(uart0Queue, &uart0Buf, portMAX_DELAY);
    data = uart0Buf.data;
    printf("Received: ");
    for(int i = 0 ; i < uart0Buf.len; i++)
      printf("%c", uart0Buf.data[i]);
    printf("\n");
    if(data[0] == 'S' && data[1] == 'T' && data[2] == 'R'){
      static uint16_t duty_l;
      static uint16_t duty_r;
      switch (data[3])
      {
      case 0:
        duty_l = 0;
        break;
      case 1:
        duty_l = data[5]*0x100+data[6];
        break;
      case 2:
        duty_l = -(data[5]*0x100+data[6]);
        break;
      default:
        printf("error left speed control");
        break;
      }
      switch (data[4])
      {
      case 0:
        duty_r = 0;
        break;
      case 1:
        duty_r = data[5]*0x100+data[6];
        break;
      case 2:
        duty_r = -(data[5]*0x100+data[6]);
        break;
      default:
        printf("error right speed control");
        break;
      }
      Motor_SetSpeed(duty_l, duty_r);
    }


    /* 手动清空数据缓冲区，否则会堆积到堆溢出 */
    free(uart0Buf.data);
  }
}
/**
 * @brief    serial0_handle_Task 任务函数
 * @brief    负责处理串口0传输的数据
 */
void serial2_handle_Task(void *pvParameters)
{
  uartBuf_t uart2Buf;
  uint8_t *data = NULL;
  while (1){
    xQueueReceive(uart2Queue, &uart2Buf, portMAX_DELAY);
    data = uart2Buf.data;
    printf("Received: ");
    for(int i = 0 ; i < uart2Buf.len; i++)
      printf("%c", uart2Buf.data[i]);
    printf("\n");
    if(data[0] == 'S' && data[1] == 'T' && data[2] == 'R'){
      static uint16_t duty_l;
      static uint16_t duty_r;
      switch (data[3])
      {
      case 0:
        duty_l = 0;
        break;
      case 1:
        duty_l = data[5]*0x100+data[6];
        break;
      case 2:
        duty_l = -(data[5]*0x100+data[6]);
        break;
      default:
        printf("error left speed control");
        break;
      }
      switch (data[4])
      {
      case 0:
        duty_r = 0;
        break;
      case 1:
        duty_r = data[5]*0x100+data[6];
        break;
      case 2:
        duty_r = -(data[5]*0x100+data[6]);
        break;
      default:
        printf("error right speed control");
        break;
      }
      Motor_SetSpeed(duty_l, duty_r);
    }


    /* 手动清空数据缓冲区，否则会堆积到堆溢出 */
    free(uart2Buf.data);
  }
}

// 初始化使用到的串口和任务
void serial_init(void){
  Timer5_Init(80000-1); // 定时器 ms 级中断，专用给串口接收
  uart0Queue = xQueueCreate(16, sizeof(uartBuf_t)); // 创建一个触发等级为缓冲区满的流缓冲区
  uart0Buf.data = (uint8_t *)malloc(UART0_BUF_LEN);
  uart0Buf.len = 0;
  uart0Buf.period = 0xFF;
  uart2Queue = xQueueCreate(16, sizeof(uartBuf_t)); // 创建一个触发等级为缓冲区满的流缓冲区
  uart2Buf.data = (uint8_t *)malloc(UART2_BUF_LEN);
  uart2Buf.len = 0;
  uart2Buf.period = 0xFF;
  Uart0_Init(115200); // LOG serial
  Uart2_Init(115200); // core module serial
  xTaskCreate(serial0_handle_Task, "serial0_handle_Task", 128, NULL, 3, NULL); /* 串口数据处理任务 */
  xTaskCreate(serial2_handle_Task, "serial2_handle_Task", 128, NULL, 3, NULL); /* 串口数据处理任务 */
}

//初始化串口0和中断
void Uart0_Init(uint32_t baud){
    // Enable the GPIO Peripheral used by the UART.
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

    // Enable UART Peripheral
    SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);

    // Configure GPIO Pins for UART mode.
    GPIOPinConfigure(GPIO_PA0_U0RX);
    GPIOPinConfigure(GPIO_PA1_U0TX);
    GPIOPinTypeUART(GPIOA_BASE, GPIO_PIN_0 | GPIO_PIN_1);

    // Use the internal 16MHz oscillator as the UART clock source.
    UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC);

    // Initialize the UART for console I/O.
    UARTStdioConfig(0, baud, 16000000);

    // Set usart int priorityset
    IntPrioritySet(INT_UART0, 3<<5);

    // Enable UART receive interrupt and receive timeout interrupt
    UARTIntEnable(UART0_BASE,UART_INT_RX | UART_INT_RT);

    // Enable UART0 interrupt
    IntEnable(INT_UART0);
}

//初始化串口2和中断
void Uart2_Init(uint32_t baud){
    // Enable the GPIO Peripheral used by the UART.
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);

    // Enable UART Peripheral
    SysCtlPeripheralEnable(SYSCTL_PERIPH_UART2);
    /* Unlock PD7 */
    HWREG(GPIOD_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY;
    HWREG(GPIOD_BASE + GPIO_O_CR) = GPIO_PIN_7;
    // Configure GPIO Pins for UART mode.
    GPIOPinConfigure(GPIO_PD6_U2RX);
    GPIOPinConfigure(GPIO_PD7_U2TX);
    GPIOPinTypeUART(GPIOD_BASE, GPIO_PIN_6 | GPIO_PIN_7);

    // Use the internal 16MHz oscillator as the UART clock source.
    UARTClockSourceSet(UART2_BASE, UART_CLOCK_PIOSC);

    // Initialize the UART for console I/O.
    UARTStdioConfig(2, baud, 16000000);//16Mhz

    // Set usart int priorityset
    IntPrioritySet(INT_UART2,3<<5);

    // Enable UART receive interrupt and receive timeout interrupt
    UARTIntEnable(UART2_BASE,UART_INT_RX | UART_INT_RT);

    // Enable UART interrupt
    IntEnable(INT_UART2);
}

// 串口0中断
void UART0_Handler(void)
{
  uint32_t flag = UARTIntStatus(UART0_BASE, true);
  if (flag == UART_INT_RX || flag == UART_INT_RT)
  {
    while (UARTCharsAvail(UART0_BASE))
    {
      if(uart0Buf.len < UART0_BUF_LEN){
        uart0Buf.period = 0;
        uart0Buf.data[uart0Buf.len++] = UARTCharGet(UART0_BASE);
      }
      else{
        uart0Buf.len=0; // 超长了，清零接收下标
      }
    }
  }
  UARTIntClear(UART0_BASE, flag);
}

// 串口2中断
void UART2_Handler(void)
{
  uint32_t flag = UARTIntStatus(UART2_BASE, true);
  if (flag == UART_INT_RX || flag == UART_INT_RT)
  {
    while (UARTCharsAvail(UART2_BASE))
    {
      if(uart2Buf.len < UART2_BUF_LEN){
        uart2Buf.period = 0;
        uart2Buf.data[uart2Buf.len++] = UARTCharGet(UART2_BASE);
      }
      else{
        uart2Buf.len=0; // 超长了，清零接收下标
      }
    }
  }
  UARTIntClear(UART2_BASE, flag);
}

// 指定串口发送数据
void UART_send_bytes(uint32_t ui32Base, uint8_t *buf, uint32_t len){
  for(uint32_t i = 0; i < len; i++)
    UARTCharPut(ui32Base, buf[i]);
}


//重定向printf函数
int fputc(int ch, FILE *f)
{
    UARTCharPut(UART0_BASE, ch);
    return (ch);
}
int fgetc(FILE *f)
{
    int ch = UARTCharGet(UART0_BASE);
    return (ch);
}
